use std::sync::Arc;

use crate::{common::AppContext, config, controller::create_route};
use sea_orm::{Database, DatabaseConnection};
use tracing_subscriber::Layer;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;

pub async fn run() -> anyhow::Result<()> {
    // 初始化环境变量
    let app_config = Arc::new(config::AppConfig::new());
    // 初始化log
    use tracing_subscriber::EnvFilter;
    use tracing_subscriber::fmt::format;

    // 输出到文件
    let file_appender = tracing_appender::rolling::daily(
        &app_config.logging.filepath,
        &app_config.logging.filename,
    );
    let file_layer = tracing_subscriber::fmt::layer()
        .with_writer(file_appender)
        .event_format(format().pretty())
        .with_ansi(false)
        .with_filter(EnvFilter::new(&app_config.logging.level));

    // 输出到控制台
    let console_layer = tracing_subscriber::fmt::layer()
        .with_writer(std::io::stdout)
        .with_ansi(true)
        .with_filter(EnvFilter::new(&app_config.logging.level));

    // 注册
    tracing_subscriber::registry()
        .with(file_layer)
        .with(console_layer)
        .init();

    // 初始化数据库
    let db: DatabaseConnection = Database::connect(&app_config.datasource.url).await?;
    let app_context = AppContext {
        db,
        env: app_config.clone(),
    };
    // 初始化axum
    let router = create_route(app_context);
    // 启动服务
    let listener = tokio::net::TcpListener::bind(&app_config.server.listen).await?;
    axum::serve(listener, router).await?;

    Ok(())
}
